/**
 * @author        Nicolas Bottarini <nicolasbottarini@gmail.com>, 404 <http://www.proyecto404.com>
 * @version       $Rev: 3 $
 * @lastrevision  $Date: 2011-09-12 16:45:37 +0000 (Mon, 12 Sep 2011) $	 
 */
package com.proyecto404.core.mvc {
	import com.proyecto404.core.BaseObject;
	import com.proyecto404.core.EventArgs;
	import com.proyecto404.core.configuration.PreloaderInfo;
	import com.proyecto404.core.exception.InvalidOperationException;
	import com.proyecto404.core.exception.InvalidPreloaderClassException;
	import com.proyecto404.core.exception.NotImplementedException;
	import com.proyecto404.core.io.DisplayObjectLoadedEventArgs;
	import com.proyecto404.core.io.DisplayObjectLoader;
	import com.proyecto404.core.log.fireflash.Console;
	import com.proyecto404.core.util.FileHelper;
	
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	
	public class Navigator extends BaseObject {
		private var _currentView:View;
		private var _currentLayout:LayoutView;
		private var _container:DisplayObjectContainer;
		private var _popupManager:PopupManager;
		private var _application:Application;
		
		public function Navigator(container:DisplayObjectContainer, popupManager:PopupManager, application:Application) {
			super();
			_container = container;
			_popupManager = popupManager; //new DefaultPopupManager(rootDisplayObject);
			_application = application;
		}
		
		public function setLayoutByName(layoutName:String, viewName:String, model:* = null):void {
			// TODO: Implementar preloader
			var layout:LayoutView = _application.library.getLayout(layoutName);
			var view:View = _application.library.getView(viewName, model);
			setLayout(layout, view);
		}
		
		public function setLayout(layout:LayoutView, view:View):void {
			Console.debug("[Navigator] showing layout '" + layout.viewName + "'");
			if (_popupManager.currentPopup != null) {
				_popupManager.closePopup();
			}
			if (_currentLayout != null) {
				_currentLayout.closed.addOnce(function(e:EventArgs):void {
					doSetLayout(layout, view);
				});
				_currentLayout.close();
			} else {
				doSetLayout(layout, view);
			}
		}
		
		private function doSetLayout(layout:LayoutView, view:View):void {
			if (_currentLayout != null) {
				_container.removeChild(_currentLayout);
			}
			_currentLayout = layout;
			_container.addChild(layout);
			_currentLayout.opened.addOnce(function(e:EventArgs):void {
				setView(view);
			});
			_currentLayout.open();
		}
		
		public function setViewByName(viewName:String, model:* = null, holderName:String = "mainHolder"):void {
			if (_application.library.containsView(viewName)) {
				var view:View = _application.library.getView(viewName, model);
				setView(view, holderName);
				return;
			}
			var viewInfo:ViewInfo = _application.configuration["views: " + viewName] as ViewInfo;
			var preloaderName:String = viewInfo.preloadedWith;
			Console.debug("[Navigator] preloading view '" + viewName + "' with preloader '" + preloaderName + "'");
			var preloaderLoader:PreloaderLoader = new PreloaderLoader(_application);
			preloaderLoader.loaded.add(function(e:PreloaderLoadedEventArgs):void {
				onPreloaderLoaded(e, viewName, model);
			});
			preloaderLoader.loadError.add (function(e:EventArgs):void {
				throw new InvalidOperationException("No se ha podido cargar el archivo del preloader:" + preloaderName);
			});
			preloaderLoader.load(preloaderName);
		}
		
		private function onPreloaderLoaded(e:PreloaderLoadedEventArgs, viewName:String, model:* = null, isPopup:Boolean = false):void {
			// TODO: Implementar preloader para popups
			e.preloaderView.closed.addOnce(function(e:EventArgs):void {
				var view:View = _application.library.getView(viewName, model);
				setView(view);
			});
			setView(e.preloaderView);
		}

		public function setView(view:View, holderName:String = "mainHolder"):void {
			Console.debug("[Navigator] showing view '" + view.viewName + "' in holder '" + holderName + "'");
			
			if (_popupManager.currentPopup != null) {
				_popupManager.closePopup();
			}
			if (_currentLayout != null) {
				_currentLayout.viewChanged.add(function(e:EventArgs):void {
					_currentView = _currentLayout.currentView;	
				});
				_currentLayout.setView(view, holderName);
				
			} else {
				if (_currentView != null && _currentView.isOpened()) {
					_currentView.closed.addOnce(function(e:EventArgs):void {
						doSetView(view);
					});
					_currentView.close();
				} else {
					doSetView(view);
				}
			}
		}
		
		private function doSetView(view:View):void {
			if (_currentView != null) {
				_container.removeChild(_currentView);
			}
			_currentView = view;
			_container.addChild(view);
			_currentView.open();
		}
		
		public function get currentLayout():LayoutView {
			return _currentLayout;
		}

		public function get currentView():View {
			return _currentView;
		}
		
		public function showPopupByName(viewName:String, model:* = null, onClose:Function = null):void {
			var view:View = _application.library.getView(viewName, model);
			showPopup(view, onClose);
		}
		
		public function showPopup(view:View, onClose:Function = null):void {
			Console.debug("[Navigator] showing popup '" + view.viewName + "'");
			_popupManager.showPopup(view, onClose);
		}

		public function get currentPopup():View {
			return _popupManager.currentPopup;
		}
		
		public function closePopup(onClose:Function = null):void {
			_popupManager.closePopup(onClose);
		}

	}
}